package com.kobeliu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;
import com.kobeliu.api.feign.SysParamFeign;
import com.kobeliu.base.BaseInfoProperties;
import com.kobeliu.enums.AggsUserType;
import com.kobeliu.exceptions.GraceException;
import com.kobeliu.exceptions.MyCustomException;
import com.kobeliu.mapper.*;
import com.kobeliu.pojo.*;
import com.kobeliu.pojo.bo.EditResumeBO;
import com.kobeliu.pojo.bo.SearchResumesBO;
import com.kobeliu.pojo.eo.AggsUserEO;
import com.kobeliu.pojo.vo.ResumeVO;
import com.kobeliu.pojo.vo.SearchResumesVO;
import com.kobeliu.result.GraceJSONResult;
import com.kobeliu.result.ResponseStatusEnum;
import com.kobeliu.service.ResumeService;
import com.kobeliu.utils.LocalDateUtils;
import com.kobeliu.utils.PagedGridResult;
import io.seata.common.util.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DateFormat;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Service
public class ResumeServiceImpl extends BaseInfoProperties implements ResumeService {

    @Autowired
    private ResumeMapper resumeMapper;

    @Autowired
    private ResumeWorkExpMapper expMapper;

    @Autowired
    private ResumeProjectExpMapper proExpMapper;

    @Autowired
    private ResumeEducationMapper eduMapper;

    @Autowired
    private ResumeExpectMapper expectMapper;

    @Autowired
    private SysParamFeign sysParamFeign;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ResumeMapperCustom resumeMapperCustom;

    @Transactional
    @Override
    public String initResume(String userId) {

        Resume resume = new Resume();

        resume.setUserId(userId);
        resume.setCreateTime(LocalDateTime.now());
        resume.setUpdatedTime(LocalDateTime.now());

        resumeMapper.insert(resume);
        return resume.getId();

    }

    @Override
    public ResumeVO getByUserId(String userId) {

        //由于数据量大，且不易变动，采用redis缓存
        String resumeJson = redis.get(REDIS_RESUME_INFO + ":" + userId);

        if(StringUtils.isNotBlank(resumeJson)){
            ResumeVO vo = new Gson().fromJson(resumeJson,ResumeVO.class);
            return vo;
        }else{
            Resume resume = null;
            ResumeVO pending = new ResumeVO();;

            CompletableFuture<Resume> future = CompletableFuture.supplyAsync(()->{
                //1.拿取resume数据
                return resumeMapper.selectOne(new QueryWrapper<Resume>()
                        .eq("user_id",userId));
            },threadPoolExecutor);

            try{
                //阻塞等待
                resume = future.get();
            }catch (Exception e){
                GraceException.display(ResponseStatusEnum.RESUME_IS_NOT_EXIST);
            }
            if(resume == null){
                GraceException.display(ResponseStatusEnum.RESUME_IS_NOT_EXIST);
            }else{
                BeanUtils.copyProperties(resume,pending);


            }
            String resumeId = resume.getId();

            CompletableFuture<Void> workFuture = CompletableFuture.runAsync(()->{
                //2.拿取workExp的数据
                List<ResumeWorkExp> workExps = expMapper.selectList(new QueryWrapper<ResumeWorkExp>()
                                                                    .eq("user_id",userId)
                                                                    .eq("resume_id",resumeId)
                                                                    .orderByDesc("begin_date"));
                pending.setWorkExpList(workExps);
            },threadPoolExecutor);

            CompletableFuture<Void> projectFuture = CompletableFuture.runAsync(()->{
                //3.拿取ResumeProjectExp数据
                List<ResumeProjectExp>  projectExpList = proExpMapper.selectList(new QueryWrapper<ResumeProjectExp>()
                                                                                .eq("user_id",userId)
                                                                                .eq("resume_id",resumeId)
                                                                                .orderByDesc("begin_date"));
                pending.setProjectExpList(projectExpList);
            },threadPoolExecutor);

            CompletableFuture<Void> eduFuture = CompletableFuture.runAsync(()->{
                //4.拿取教育经历
                List<ResumeEducation> educationList = eduMapper.selectList(new QueryWrapper<ResumeEducation>()
                                                                            .eq("user_id",userId)
                                                                            .eq("resume_id",resumeId)
                                                                            .orderByDesc("begin_date"));
                pending.setEducationList(educationList);
            },threadPoolExecutor);

            //三个编排任务要全部完成
            CompletableFuture<Void> allOf = CompletableFuture.allOf(workFuture, projectFuture, eduFuture);

            //阻塞等待全部完成
            try {
                allOf.get();
            } catch (Exception e) {
                throw new MyCustomException(ResponseStatusEnum.RESUME_IS_NOT_EXIST);
            }

            //存入缓存
            redis.set(REDIS_RESUME_INFO+":"+userId,new Gson().toJson(pending),60);
            return pending;
        }


    }

    @Transactional
    @Override
    public void updateResume(EditResumeBO bo) {

        Resume pending = new Resume();
        BeanUtils.copyProperties(bo,pending);
        pending.setUpdatedTime(LocalDateTime.now());
        resumeMapper.update(pending,new QueryWrapper<Resume>()
                .eq("id",bo.getId())
                .eq("user_id",pending.getUserId()));

    }

    @Transactional
    @Override
    public void refresh(String userId, String resumeId) {

        String today = LocalDateUtils.getLocalDateStr();
        //redis中读
        String countsStr = redis.get(USER_ALREADY_REFRESHED_COUNTS+":"+userId+":"+today);
        Integer maxCounts = null;

        if(StringUtils.isNotBlank(countsStr)){
            maxCounts = Integer.parseInt(countsStr);
        }else {
            //查询最大刷新次数
            maxCounts = sysParamFeign.paramsByFeign();
        }
        if(maxCounts == null)
            maxCounts = 3;
        if(maxCounts<1){
            //当天刷新次数不够了
            GraceException.display(ResponseStatusEnum.RESUME_MAX_LIMIT_ERROR);
        }

        this.refreshResume(userId,resumeId);
        --maxCounts;
        //redis中存
        redis.set(USER_ALREADY_REFRESHED_COUNTS+":"+userId+":"+today,maxCounts+"");
    }

    @Override
    public List<ResumeExpect> getMyResumeExpectList(String resumeId, String userId) {
        return expectMapper.selectList(new QueryWrapper<ResumeExpect>()
                .eq("resume_id",resumeId)
                .eq("user_id",userId));
    }

    @Override
    public PagedGridResult searchResumes(SearchResumesBO searchResumesBO, Integer page, Integer limit) {

        String basicTitle = searchResumesBO.getBasicTitle();
        String jobType = searchResumesBO.getJobType();
        Integer beginAge = searchResumesBO.getBeginAge();
        Integer endAge = searchResumesBO.getEndAge();
        Integer sex = searchResumesBO.getSex();
        Integer activeTimes = searchResumesBO.getActiveTimes();
        Integer beginWorkExpYears = searchResumesBO.getBeginWorkExpYears();
        Integer endWorkExpYears = searchResumesBO.getEndWorkExpYears();
        String edu = searchResumesBO.getEdu();
        List<String> eduList = searchResumesBO.getEduList();
        Integer beginSalary = searchResumesBO.getBeginSalary();
        Integer endSalary = searchResumesBO.getEndSalary();
        String jobStatus = searchResumesBO.getJobStatus();

        Map<String, Object> map = new HashMap<>();
        map.put("basicTitle", basicTitle);
        map.put("jobType", jobType);
        map.put("beginAge", beginAge);
        map.put("endAge", endAge);
        map.put("sex", sex);
        map.put("activeTimes", activeTimes);
        map.put("beginWorkExpYears", beginWorkExpYears);
        map.put("endWorkExpYears", endWorkExpYears);
        map.put("edu", edu);
        map.put("eduList", eduList);
        map.put("beginSalary", beginSalary);
        map.put("endSalary", endSalary);
        map.put("jobStatus", jobStatus);

        List<SearchResumesVO> list = resumeMapperCustom.searchResumesList(map);

        return setterPagedGrid(list, page);
    }

    private void refreshResume(String userId, String resumeId){
        EditResumeBO bo = new EditResumeBO();

        bo.setId(resumeId);
        bo.setUserId(userId);
        bo.setRefreshTime(LocalDateTime.now());

        this.updateResume(bo);
    }
}
